﻿using System;
using System.Windows.Forms;
using Microsoft.WowAddonStudio.FrameXml.Components;
using Microsoft.WowAddonStudio.FrameXml.Components.Support;
using Microsoft.WowAddonStudio.FrameXml.Serialization.LayoutFrames;

namespace Microsoft.WowAddonStudio.FrameXml.Editor.ToolWindows
{
	/// <summary>
	/// 
	/// </summary>
	public sealed partial class HierarchicalLayoutControllerHost : UserControl, ILayoutControllerHost
	{
	    /// <summary>
	    /// Occurs when [layout state changed].
	    /// </summary>
	    public event EventHandler<LayoutStateChangedEventArgs> LayoutStateChanged;

	    /// <summary>
	    /// Occurs when [frame control state changed].
	    /// </summary>
	    public event EventHandler<FrameControlStateChangedEventArgs> FrameControlStateChanged;

	    /// <summary>
	    /// Occurs when [frame control selected].
	    /// </summary>
	    public event EventHandler<FrameControlSelectedEventArgs> FrameControlSelected;

		private readonly ImageList treeViewImages;
		private readonly ImageList treeViewStateImages;
		private TreeView layoutTree;
	    private TreeNode selectedNode;

		/// <summary>
		/// Initializes a new instance of the <see cref="HierarchicalLayoutControllerHost"/> class.
		/// </summary>
		public HierarchicalLayoutControllerHost()
		{
			InitializeComponent();

			layoutTree = new TreeView {CheckBoxes = true};

			//add images to treeViewImages
			treeViewImages = LayoutImageList.DefaultImages;
			treeViewStateImages = LayoutImageList.DefaultStateImages;
			AddTreeView(layoutTree);

			collapseAllToolStripMenuItem.Image = Resources.Collapse_small;
			expandAllToolStripMenuItem.Image = Resources.Expand_small;
			refreshToolStripMenuItem.Image = Resources.Refresh;
			showToolStripMenuItem.Image = Resources.Hiddenfield;
			showAllControlsToolStripMenuItem.Image = Resources.ShowGridlines;
		}

		/// <summary>
		/// Gets or sets the TreeView object for the unfiltered (hierarchical) view.
		/// </summary>
		/// <returns>A TreeView object.</returns>
		public TreeView LayoutTree
		{
			get { return layoutTree; }
			set
			{
				RemoveTreeView(layoutTree);
				layoutTree = value;
				AddTreeView(layoutTree);
			}
		}

		/// <summary>
		/// Adds the tree view.
		/// </summary>
		/// <param name="treeView">The tree view.</param>
		private void AddTreeView(TreeView treeView)
		{
			if (treeView == null)
				throw new ArgumentNullException("treeView");

			treeView.BeforeCheck += OnTreeBeforeCheck;
			treeView.BeforeSelect += OnTreeBeforeSelect;
		    treeView.NodeMouseClick += OnTreeNodeMouseClick;
		    treeView.NodeMouseDoubleClick += OnTreeNodeMouseDoubleClick;

			Controls.Add(treeView);

			treeView.Dock = DockStyle.Fill;
			treeView.ImageList = treeViewImages;
			treeView.StateImageList = treeViewStateImages;
			treeView.HideSelection = false;
			treeView.ContextMenuStrip = TreeContextMenu;
		}

        /// <summary>
        /// Called when [tree node mouse double click].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.TreeNodeMouseClickEventArgs"/> instance containing the event data.</param>
	    private void OnTreeNodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
	    {
            if (e.Node != null && e.Node.Tag is Control)
            {
                Control control = (Control) e.Node.Tag;
                var serializationObject = ((IFrameXmlComponent) control).SerializationObject;
                if (serializationObject is LayoutFrame)
                {
                    var layoutFrame = (LayoutFrame) serializationObject;

                    if(layoutFrame.Virtual && layoutFrame.LayoutHidden)
                    {
                        if (LayoutStateChanged != null)
                            LayoutStateChanged(this, new LayoutStateChangedEventArgs(LayoutShowState.VirtualOnly, selectedNode));
                    }
                    else if (layoutFrame.Virtual && !layoutFrame.LayoutHidden)
                    {
                        if (LayoutStateChanged != null)
                            LayoutStateChanged(this, new LayoutStateChangedEventArgs(LayoutShowState.All));
                    }
                }
            }            
	    }

	    /// <summary>
        /// Called when [tree node mouse click].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.TreeNodeMouseClickEventArgs"/> instance containing the event data.</param>
	    private void OnTreeNodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
	    {
            // Select the node
	        e.Node.TreeView.SelectedNode = e.Node;
	    }
        
	    /// <summary>
		/// Called when [tree before select].
		/// </summary>
		/// <param name="sender">The sender.</param>
		/// <param name="e">The <see cref="System.Windows.Forms.TreeViewCancelEventArgs"/> instance containing the event data.</param>
		private void OnTreeBeforeSelect(object sender, TreeViewCancelEventArgs e)
		{
		    selectedNode = e.Node;

            this.showToolStripMenuItem.Visible = false;
            this.showAllControlsToolStripMenuItem.Visible = true;
            
            if (e.Node != null && e.Node.Tag is Control)
            {
                Control control = (Control) e.Node.Tag;
                var serializationObject = ((IFrameXmlComponent) control).SerializationObject;
                if(serializationObject is LayoutFrame)
                {
                    var layoutFrame = (LayoutFrame) serializationObject;
                    this.showToolStripMenuItem.Visible = layoutFrame.Virtual;
                    this.showAllControlsToolStripMenuItem.Visible = !layoutFrame.Virtual;
                    this.toolStripMenuItem1.Visible = true;

                    if (layoutFrame.Virtual && layoutFrame.LayoutHidden)
                    {
                        showToolStripMenuItem.Text = "Edit contol";
                        showToolStripMenuItem.Tag = LayoutShowState.VirtualOnly;
                    }
                    else if (layoutFrame.Virtual && !layoutFrame.LayoutHidden)
                    {
                        showToolStripMenuItem.Text = "End editing control";
                        showToolStripMenuItem.Tag = LayoutShowState.All;
                    }
                    else
                    {
                        this.showToolStripMenuItem.Visible = false;
                        this.showAllControlsToolStripMenuItem.Visible = false;
                        this.toolStripMenuItem1.Visible = false;
                    }
                }
            }

		    if (FrameControlSelected != null)
		        FrameControlSelected(sender, new FrameControlSelectedEventArgs(e.Node.Name));
		}

		/// <summary>
		/// Removes the tree view.
		/// </summary>
		/// <param name="treeView">The tree view.</param>
		private void RemoveTreeView(TreeView treeView)
		{
			if (treeView != null)
			{
				treeView.BeforeCheck -= OnTreeBeforeCheck;
				treeView.BeforeSelect -= OnTreeBeforeSelect;
                treeView.NodeMouseClick -= OnTreeNodeMouseClick;
                treeView.NodeMouseDoubleClick -= OnTreeNodeMouseDoubleClick;
			}
		}

		/// <summary>
		/// Called when [tree before check].
		/// </summary>
		/// <param name="sender">The sender.</param>
		/// <param name="e">The <see cref="System.Windows.Forms.TreeViewCancelEventArgs"/> instance containing the event data.</param>
		private void OnTreeBeforeCheck(object sender, TreeViewCancelEventArgs e)
		{
			if (FrameControlStateChanged != null)
			{
				var arg = new FrameControlStateChangedEventArgs(e.Node.Name, e.Node.Checked, e.Node);
				FrameControlStateChanged(sender, arg);
				e.Cancel = arg.Cancel;
			}
		}

		/// <summary>
		/// Handles the Click event of the expandAllToolStripMenuItem control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void expandAllToolStripMenuItem_Click(object sender, EventArgs e)
		{
			layoutTree.ExpandAll();
		}

		/// <summary>
		/// Handles the Click event of the collapseAllToolStripMenuItem control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void collapseAllToolStripMenuItem_Click(object sender, EventArgs e)
		{
			layoutTree.CollapseAll();
		}

		/// <summary>
		/// Handles the Click event of the showAllControlsToolStripMenuItem control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void ShowAllControlsMenuItemClick(object sender, EventArgs e)
		{
			if(LayoutStateChanged != null)
				LayoutStateChanged(this, new LayoutStateChangedEventArgs(LayoutShowState.All));
		}

		/// <summary>
		/// Handles the Click event of the showToolStripMenuItem control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void ShowVirtualControlMenuItemClick(object sender, EventArgs e)
		{
		    var layoutShowState = showToolStripMenuItem.Tag is LayoutShowState ? (LayoutShowState) showToolStripMenuItem.Tag : LayoutShowState.Undefine;

            if (layoutShowState == LayoutShowState.All)
            {
                if (LayoutStateChanged != null)
                    LayoutStateChanged(this, new LayoutStateChangedEventArgs(LayoutShowState.All));
            }
            else
            {
                if (LayoutStateChanged != null)
                    LayoutStateChanged(this, new LayoutStateChangedEventArgs(LayoutShowState.VirtualOnly, selectedNode));
            }
		}

		/// <summary>
		/// Handles the Click event of the refreshToolStripMenuItem control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void refreshToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (LayoutStateChanged != null)
				LayoutStateChanged(this, new LayoutStateChangedEventArgs(LayoutShowState.RefreshAll));
		}
	}
}